{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "### 图像简介\n",
    "* 在计算机眼中，Lena 这个人的图像被分成很多很多个小方格。\n",
    "* 每一个小格叫做一个像素点，计算机就是由这些像素点组成一张图像的。\n",
    "* 每一个像素点有 RGB 三个通道，每个通道的值在 0-255 之间，0 表示黑的，255 表示非常亮。\n",
    "* 图像长宽有多少个像素，RGB 矩阵就有多大。 \n",
    "* RGB 叫图像的颜色通道，通常情况下，我们看到的一个彩色图都是 RGB 三颜色通道的。\n",
    "* 灰度图(或黑白图)只用一个通道来表示它的亮度就足够了。\n",
    "* RGB 矩阵的大小和图像的大小一样，若图像的像素点宽 500 长 500，则得到 [500,500,3] 的矩阵，这里的 3 就是 3 通道。\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "d7e7f7a67f9fb9b9"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "\n",
    "\n",
    "\"\"\"\n",
    "cv2.imread(filename, flag) \n",
    "    filename: 文件路径\n",
    "    flag    ： 读取方式（IMREAD_GRAYSCALE：灰度图片；IMREAD_COLOR：彩色图片；……）\n",
    "\"\"\"\n",
    "import cv2\n",
    "\n",
    "path = './images/img_0.png'\n",
    "\n",
    "image = cv2.imread(path, cv2.IMREAD_COLOR)  # 读取图片\n",
    "print(type(image))  # <class 'numpy.ndarray'> 数据类型\n",
    "\n",
    "print(image.shape)  # (1536, 1024, 3)  第一个代表图片高度，第二个代表图片宽度，第三方代表通道数，彩色图像通道数为3，灰度图像通道数为1\n",
    "\n",
    "print(image)  # 图片数据\n",
    "\n",
    "cv2.imshow('Image', image)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "1c21d763652f8e30"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 通道处理\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "8e9708f7274eec72"
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "cv2.resize(srcdst = cv.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])\n",
    "    src\t    numpy.ndarray\t是\t原图像\n",
    "    dsize\ttuple<int>\t    是\t缩放后的图像大小\n",
    "    dst\t    无所谓\t        否\t目标图像，但是在 Python 里面没有任何意义。一般不传参或者设成 None\n",
    "    fx, fy\t数值类型\t        否\tx 和 y 方向上的缩放比例\n",
    "    interpolation\t int\t否\t插值方式表示代码，本质是一个 int 数值，一般用 OpenCV 内置的参数代号以提高可读性。\n",
    "\n",
    "cv2.cvtColor(p1,p2)     颜色空间转换函数，p1是需要转换的图片，p2是转换成何种格式\n",
    "cv2.split()     分离通道\n",
    "cv2.merge()     合并通道\n",
    "\"\"\"\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "path = './images/img_0.png'\n",
    "\n",
    "image = cv2.imread(path, cv2.IMREAD_COLOR)  # 以彩色方式读取图片\n",
    "height, width, channels = image.shape\n",
    "_width = 400\n",
    "_height = _width * height // width\n",
    "image = cv2.resize(image, (_width, _height))  # 等比例缩放图片\n",
    "b, g, r = cv2.split(image)  # 分离出图片的B,R,G颜色通道\n",
    "\n",
    "# cv2.imshow('Image B', b)\n",
    "# cv2.imshow('Image G', g)\n",
    "# cv2.imshow('Image R', r)\n",
    "image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
    "all_images = np.hstack((b, g, r, image_gray))  # 拼接图片，注意：高度和通道数一致\n",
    "cv2.imshow('All Image', all_images)\n",
    "\n",
    "_image = cv2.merge((b, g, r))\n",
    "cv2.imshow('Image Old', _image)\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-26T08:06:19.012501300Z",
     "start_time": "2024-04-26T08:05:08.141140900Z"
    }
   },
   "id": "4e7af6ff8143fdd2"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 通道提取"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "55577db08afaff25"
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "\n",
    "\"\"\"\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "path = './images/img_0.png'\n",
    "\n",
    "image = cv2.imread(path, cv2.IMREAD_COLOR)  # 以彩色方式读取图片\n",
    "height, width, _ = image.shape\n",
    "_width = 400\n",
    "_height = _width * height // width\n",
    "image = cv2.resize(image, (_width, _height))  # 等比例缩放图片\n",
    "\n",
    "image_b = image.copy()\n",
    "image_b[:, :, 1] = 0\n",
    "image_b[:, :, 2] = 0\n",
    "\n",
    "image_g = image.copy()\n",
    "image_g[:, :, 0] = 0\n",
    "image_g[:, :, 2] = 0\n",
    "\n",
    "image_r = image.copy()\n",
    "image_r[:, :, 0] = 0\n",
    "image_r[:, :, 1] = 0\n",
    "all_images = np.hstack((image_b, image_g, image_r))\n",
    "\n",
    "cv2.imshow('All Image', all_images)\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-26T08:24:23.615792100Z",
     "start_time": "2024-04-26T08:24:17.491367100Z"
    }
   },
   "id": "ffb7640c6c61fea3"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 获取图片坐标位置"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "44aa64c55df7bd0e"
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "画圆（圆点）\n",
    "cv2.circle(image, center, radius, color[, thickness[, lineType[, shift]]])\n",
    "    image：      输入的图片data\n",
    "    center：     圆心位置\n",
    "    radius：     圆的半径\n",
    "    color：      圆的颜色\n",
    "    thickness：  圆形轮廓的粗细（如果为正）。负厚度表示要绘制实心圆。\n",
    "    lineType：   圆边界的类型。\n",
    "    shift：      中心坐标和半径值中的小数位数。\n",
    "    \n",
    "写内容\n",
    "cv2.putText(image, text, point, fontFace, scale, color, thickness)\n",
    "    image       图片\n",
    "    text        要添加的文字\n",
    "    point       文字添加到图片上的位置\n",
    "    fontFace    字体的类型\n",
    "    scale       字体大小\n",
    "    color       字体颜色\n",
    "    thickness   字体粗细\n",
    "\"\"\"\n",
    "import cv2\n",
    "\n",
    "path = './images/scene.png'\n",
    "\n",
    "image = cv2.imread(path, cv2.IMREAD_COLOR)  # 以彩色方式读取图片\n",
    "\n",
    "\n",
    "def mouse_click(event, x, y, flags, param):\n",
    "    if event == cv2.EVENT_LBUTTONDOWN:\n",
    "        xy = \"%d,%d\" % (x, y)\n",
    "        point = (x, y)\n",
    "        cv2.circle(image, point, 2, (255, 0, 0))\n",
    "        cv2.putText(image, xy, point, cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), thickness=2)\n",
    "        cv2.imshow('Image', image)\n",
    "    pass\n",
    "\n",
    "\n",
    "cv2.namedWindow('Image', cv2.WINDOW_NORMAL)\n",
    "cv2.setMouseCallback('Image', mouse_click)\n",
    "cv2.imshow('Image', image)\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T01:59:33.932617100Z",
     "start_time": "2024-04-28T01:58:52.512906300Z"
    }
   },
   "id": "b915bf3e28d5df32"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 图片裁剪"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "b050421fba89e605"
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "提取指定区域内的像素点\n",
    "\"\"\"\n",
    "import cv2\n",
    "\n",
    "path = './images/scene.png'\n",
    "\n",
    "image = cv2.imread(path, cv2.IMREAD_COLOR)  # 以彩色方式读取图片\n",
    "\n",
    "image_crop = image[650:830, 600:1030]\n",
    "\n",
    "cv2.imshow('Image CROP', image_crop)\n",
    "\n",
    "cv2.imwrite('./images/scene_crop.png', image_crop)\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T01:59:40.666777500Z",
     "start_time": "2024-04-28T01:59:36.557252800Z"
    }
   },
   "id": "7510656fb310a182"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 边界填充\n",
    "\n",
    "① 边界填充就是对图像进行一些变换，让原始图像进行扩大。\n",
    "\n",
    "② 边界填充的入口参数：\n",
    "- BORDER_REPLICATE：复制法，也就是复制最边缘像素。\n",
    "- BORDER_REFLECT：反射法，对感兴趣的图像中的像素在两边进行复制例如：fedcba|abcdefgh|hgfedcb   \n",
    "- BORDER_REFLECT_101：反射法，也就是以最边缘像素为轴，对称，gfedcb|abcdefgh|gfedcba\n",
    "- BORDER_WRAP：外包装法cdefgh|abcdefgh|abcdefg  \n",
    "- BORDER_CONSTANT：常量法，常数值填充。"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "d8dfd6b0c554d5af"
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "cv2.copyMakeBorder()\n",
    "    src ：                       输入的图片\n",
    "    top, bottom, left, right ：  相应方向上的边框宽度\n",
    "    borderType：                 定义要添加边框的类型，它可以是以下的一种：\n",
    "        cv2.BORDER_CONSTANT：    添加的边界框像素值为常数（需要额外再给定一个参数）\n",
    "        cv2.BORDER_REFLECT：     添加的边框像素将是边界元素的镜面反射，类似于gfedcba|abcdefgh|hgfedcba\n",
    "        cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT：和上面类似，但是有一些细微的不同，类似于gfedcb|abcdefgh|gfedcba\n",
    "        cv2.BORDER_REPLICATE：   使用最边界的像素值代替，类似于aaaaaa|abcdefgh|hhhhhhh\n",
    "        cv2.BORDER_WRAP：        不知道怎么解释，直接看吧，cdefgh|abcdefgh|abcdefg\n",
    "    value：                      如果borderType为cv2.BORDER_CONSTANT时需要填充的常数值。\n",
    "\"\"\"\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "path = './images/scene_crop.png'\n",
    "\n",
    "image = cv2.imread(path, cv2.IMREAD_COLOR)  # 以彩色方式读取图片\n",
    "\n",
    "# 设置填充边界\n",
    "top, bottom, left, right = (40, 40, 40, 40)\n",
    "\n",
    "# 复制法\n",
    "border_replicate = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_REPLICATE)\n",
    "cv2.putText(border_replicate, 'border_replicate', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), thickness=2)\n",
    "# cv2.imshow('border_replicate', border_replicate)\n",
    "\n",
    "border_reflect = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_REFLECT)\n",
    "cv2.putText(border_reflect, 'border_reflect', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), thickness=2)\n",
    "# cv2.imshow('border_reflect', border_reflect)\n",
    "\n",
    "border_reflect101 = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_REFLECT101)\n",
    "cv2.putText(border_reflect101, 'border_reflect101', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), thickness=2)\n",
    "# cv2.imshow('border_reflect101', border_reflect101)\n",
    "\n",
    "border_reflect_101 = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_REFLECT_101)\n",
    "cv2.putText(border_reflect_101, 'border_reflect_101', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), thickness=2)\n",
    "# cv2.imshow('border_reflect_101', border_reflect_101)\n",
    "\n",
    "border_wrap = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_WRAP)\n",
    "cv2.putText(border_wrap, 'border_wrap', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), thickness=2)\n",
    "# cv2.imshow('border_wrap', border_wrap)\n",
    "\n",
    "border_constant = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(255, 255, 255))\n",
    "cv2.putText(border_constant, 'border_constant', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), thickness=2)\n",
    "# cv2.imshow('border_constant', border_constant)\n",
    "\n",
    "h_image_1 = np.hstack((border_replicate, border_wrap, border_constant))\n",
    "h_image_2 = np.hstack((border_reflect, border_reflect101, border_reflect_101))\n",
    "\n",
    "v_image = np.vstack((h_image_1, h_image_2))\n",
    "cv2.imshow('Image', v_image)\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T02:16:33.947100700Z",
     "start_time": "2024-04-28T02:15:05.341547Z"
    }
   },
   "id": "1d9fe6eed898392a"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 图像融合"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "65a8d255ac9ffba2"
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None)\n",
    "    src1, src2： 需要融合相加的两副大小和通道数相等的图像\n",
    "    alpha：      src1的权重\n",
    "    beta：       src2的权重\n",
    "    gamma：      gamma修正系数，不需要修正设置为0，具体请参考《图像处理gamma修正（伽马γ校正）的原理和实现算法》\n",
    "    dst：        可选参数，输出结果保存的变量，默认值为None，如果为非None，输出图像保存到dst对应实参中，其大小和通道数与输入图像相同，图像的深度（即图像像素的位数）由dtype参数或输入图像确认\n",
    "    dtype：      可选参数，输出图像数组的深度，即图像单个像素值的位数（如RGB用三个字节表示，则为24位），选默认值None表示与源图像保持一致。\n",
    "    返回值：      融合相加的结果图像\n",
    "\"\"\"\n",
    "import cv2\n",
    "\n",
    "path = './images/scene.png'\n",
    "\n",
    "image_1 = cv2.imread('./images/scene.png', cv2.IMREAD_COLOR)  # 以彩色方式读取图片\n",
    "image_2 = cv2.imread('./images/img_0.png', cv2.IMREAD_COLOR)  # 以彩色方式读取图片\n",
    "\n",
    "# 缩放图片,保证宽度一致\n",
    "default_width = 800\n",
    "image_1_height, image_1_width, _ = image_1.shape\n",
    "image_1_height = default_width * image_1_height // image_1_width\n",
    "image_1 = cv2.resize(image_1, (default_width, image_1_height))\n",
    "\n",
    "image_2_height, image_2_width, _ = image_2.shape\n",
    "image_2_height = default_width * image_2_height // image_2_width\n",
    "image_2 = cv2.resize(image_2, (default_width, image_2_height))\n",
    "# 裁剪 image_2 ,保证高度一致\n",
    "image_2 = image_2[50: image_1.shape[0] + 50, :]\n",
    "\n",
    "# 图像融合\n",
    "image = cv2.addWeighted(image_1, 0.65, image_2, 0.35, 0)\n",
    "\n",
    "all_1 = np.hstack((image_1, image_2))\n",
    "all_2 = np.hstack((image, image))\n",
    "cv2.imshow('Image', np.vstack((all_1, all_2)))\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T02:35:27.944393400Z",
     "start_time": "2024-04-28T02:35:03.042805400Z"
    }
   },
   "id": "a20ca10e8ad5827f"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 图像阈值"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "99a02e73233bb3b5"
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "ret, image = cv2.threshold (src, thresh, maxval, type)\n",
    "    src:        源图像矩阵，单通道，8 位或 32 位浮点数据\n",
    "                注意！：这里的单通道应是指.threshold()对图像处理时按单通道依次进行处理,待处理图像矩阵可以是单通道8位图像矩阵，也可以是32为RGBA图像矩阵，具体看下方实验（这里差点搞错，误以为该函数只能处理单通道图像矩阵，感谢 小伙伴提醒！！）\n",
    "                A是Alpha色彩空间:\n",
    "                  alpha通道一般用作不透明度参数。如果一个像素的alpha通道数值为0%，那它就是完全透明的（也就是看不见的），而数值为100%则意味着一个完全不透明的像素（传统的数字图像）。在0%和100%之间的值则使得像素可以透过背景显示出来，就像透过玻璃（半透明性），这种效果是简单的二元透明性（透明或不透明）做不到的。它使数码合成变得容易。alpha通道值可以用百分比、整数或者像RGB参数那样用0到1的实数表示。\n",
    "    thresh:     阈值，取值范围0～255\n",
    "    maxval:     与阈值类型配合使用的最大值，可理解为填充色，取值范围0～255\n",
    "    type:       阈值类型\n",
    "        - cv2.THRESH_BINARY\n",
    "        - cv2.THRESH_BINARY_INV\n",
    "        - cv2.THRESH_TRUNC\n",
    "        - cv2.THRESH_TOZERO\n",
    "        - cv2.THRESH_TOZERO_INV\n",
    "\"\"\"\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "image = cv2.imread('./images/img_0.png', cv2.IMREAD_GRAYSCALE)\n",
    "image = cv2.resize(image, (0, 0), fx=0.25, fy=0.25)\n",
    "_, thresh_trunc = cv2.threshold(image, 100, 255, cv2.THRESH_TRUNC)\n",
    "_, thresh_binary = cv2.threshold(image, 100, 255, cv2.THRESH_BINARY)\n",
    "_, thresh_binary_inv = cv2.threshold(image, 100, 255, cv2.THRESH_BINARY_INV)\n",
    "_, thresh_tozero = cv2.threshold(image, 100, 255, cv2.THRESH_TOZERO)\n",
    "_, thresh_tozero_inv = cv2.threshold(image, 100, 255, cv2.THRESH_TOZERO_INV)\n",
    "\n",
    "all_1 = np.hstack((image, thresh_binary, thresh_binary_inv))\n",
    "all_2 = np.hstack((thresh_trunc, thresh_tozero, thresh_tozero_inv))\n",
    "cv2.imshow('All Images', np.vstack((all_1, all_2)))\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:21:39.772838900Z",
     "start_time": "2024-04-28T03:21:21.873101200Z"
    }
   },
   "id": "a285fec72cfc6fca"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 图像平滑处理\n",
    "\n",
    "- 均值滤波\n",
    "- 方框滤波\n",
    "- 高斯滤波\n",
    "- 中值滤波"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "60bf4a8311cb0e7c"
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "均值滤波：  dst=cv2.blur（src, ksize, anchor, borderType）\n",
    "            ● dst           返回值，表示进行均值滤波后得到的处理结果。\n",
    "            ● src           是需要处理的图像，即原始图像。它可以有任意数量的通道，并能对各个通道独立处理。图像深度应该是CV_8U、CV_16U、CV_16S、CV_32F 或者 CV_64F中的一种。\n",
    "            ● ksize         是滤波核的大小。滤波核大小是指在均值处理过程中，其邻域图像的高度和宽度。\n",
    "            ● anchor        是锚点，其默认值是（-1,-1），表示当前计算均值的点位于核的中心点位置。该值使用默认值即可，在特殊情况下可以指定不同的点作为锚点。\n",
    "            ● borderType    是边界样式，该值决定了以何种方式处理边界。一般情况下不需要考虑该值的取值，直接采用默认值即可。\n",
    "方框滤波：  dst=cv2.boxFilter（src, ddepth, ksize, anchor, normalize, borderType）\n",
    "            ● dst           返回值，表示进行方框滤波后得到的处理结果。\n",
    "            ● src           是需要处理的图像，即原始图像。它能够有任意数量的通道，并能对各个通道独立处理。图像深度应该是CV_8U、CV_16U、CV_16S、CV_32F 或者 CV_64F中的一种。\n",
    "            ● ddepth        是处理结果图像的图像深度，一般使用-1表示与原始图像使用相同的图像深度。\n",
    "            ● ksize         是滤波核的大小。滤波核大小是指在滤波处理过程中所选择的邻域图像的高 度和宽度。\n",
    "            ● anchor        是锚点，其默认值是（-1,-1），表示当前计算均值的点位于核的中心点位 置。该值使用默认值即可，在特殊情况下可以指定不同的点作为锚点。\n",
    "            ● normalize     表示在滤波时是否进行归一化（这里指将计算结果规范化为当前像素值范围内的值）处理，该参数是一个逻辑值，可能为真（值为1）或假（值为0）：\n",
    "                1.当参数normalize=1时，表示要进行归一化处理，要用邻域像素值的和除以面积。此时方框滤波与均值滤波效果相同。\n",
    "                2.当参数normalize=0时，表示不需要进行归一化处理，直接使用邻域像素值的和。当 normalize=0时，因为不进行归一化处理，因此滤波得到的值很可能超过当前像素值范围的最大值，从而被截断为最大值。这样，就会得到一幅纯白色的图像。\n",
    "            ● borderType    是边界样式，该值决定了以何种方式处理边界。\n",
    "高斯滤波：使用高斯核与输入图像中的每个点作卷积运算，然后对卷积结果进行求和，从而得到输出图像。\n",
    "        cv2.GaussianBlur（ SRC，ksize，sigmaX [，DST [，sigmaY [，borderType ] ] ] ）\n",
    "        src –输入图像；图像可以具有任何数量的信道，其独立地处理的，但深度应CV_8U，CV_16U，CV_16S，CV_32F或CV_64F。\n",
    "        dst –输出与图像大小和类型相同的图像src。\n",
    "        ksize –高斯核大小。 ksize.width 并且 ksize.height 可以有所不同，但它们都必须是正数和奇数。或者，它们可以为零，然后从计算 sigma*。\n",
    "        sigmaX – X方向上的高斯核标准偏差。\n",
    "        sigmaY – Y方向上的高斯核标准差；如果 sigmaY 为零，则将其设置为等于 sigmaX；如果两个西格玛均为零，则分别根据ksize.width 和 进行计算 ksize.height（getGaussianKernel()有关详细信息，请参见 link)；完全控制的结果，无论这一切的语义未来可能的修改，建议指定所有的ksize，sigmaX和sigmaY。\n",
    "        borderType –像素外推方法。\n",
    "        \n",
    "中值滤波：取当前像素点及其周围临近像素点（一共有奇数个像素点）的像素值，将这些像素值排序，然后将位于中间位置的像素值作为当前像素点的像素值.适合去除椒盐噪声\n",
    "         dst=cv2.medianBlur（src,ksize）\n",
    "         ● dst是返回值，表示进行中值滤波后得到的处理结果。\n",
    "         ● src 是需要处理的图像，即源图像。它能够有任意数量的通道，并能对各个通道独立处理。图像深度应该是CV_8U、CV_16U、CV_16S、CV_32F 或者 CV_64F中的一种。\n",
    "         ● ksize 是滤波核的大小。滤波核大小是指在滤波处理过程中其邻域图像的高度和宽度。需要注意，核大小必须是比1大的奇数，比如3、5、7等。\n",
    "        \n",
    "双边滤波: 双边滤波在计算某一个像素点的新值时，不仅考虑距离信息（距离越远，权重越小），还考虑色彩信息（色彩差别越大，权重越小）\n",
    "        dst=cv2.bilateralFilter（src,d,sigmaColor,sigmaSpace,borderType）\n",
    "        ● dst是返回值，表示进行双边滤波后得到的处理结果。\n",
    "        ● src 是需要处理的图像，即原始图像。它能够有任意数量的通道，并能对各通道独立处理。图像深度应该是CV_8U、CV_16U、CV_16S、CV_32F或者CV_64F中的一 种。                        \n",
    "        ● d是在滤波时选取的空间距离参数，这里表示以当前像素点为中心点的直径。如果该值为非正数，则会自动从参数 sigmaSpace 计算得到。如果滤波空间较大（d>5），则速度较慢。因此，在实时应用中，推荐d=5。对于较大噪声的离线滤波，可以选择d=9。\n",
    "        ● sigmaColor是滤波处理时选取的颜色差值范围，该值决定了周围哪些像素点能够参与到滤波中来。与当前像素点的像素值差值小于 sigmaColor 的像素点，能够参与到当前的滤波中。该值越大，就说明周围有越多的像素点可以参与到运算中。该值为0时，滤波失去意义；该值为255时，指定直径内的所有点都能够参与运算。\n",
    "        ● sigmaSpace是坐标空间中的sigma值。它的值越大，说明有越多的点能够参与到滤波计算中来。当d>0时，无论sigmaSpace的值如何，d都指定邻域大小；否则，d与 sigmaSpace的值成比例。\n",
    "        ● borderType是边界样式，该值决定了以何种方式处理边界。一般情况下，不需要考虑该值，直接采用默认值即可。\n",
    "\"\"\"\n",
    "import cv2\n",
    "\n",
    "image = cv2.imread('./images/img_0.png', cv2.IMREAD_GRAYSCALE)\n",
    "image = cv2.resize(image, (0, 0), fx=0.25, fy=0.25)\n",
    "\n",
    "# 均值滤波\n",
    "avg = cv2.blur(image, (3, 3))\n",
    "\n",
    "# 方框滤波\n",
    "box = cv2.boxFilter(image, -1, (3, 3))\n",
    "\n",
    "# 高斯滤波\n",
    "gauss = cv2.GaussianBlur(image, (3, 3), sigmaX=1)\n",
    "\n",
    "# 中值滤波\n",
    "median = cv2.medianBlur(image, 3)\n",
    "\n",
    "# 双边滤波\n",
    "bilateral = cv2.bilateralFilter(image, 3, 150, 150)\n",
    "\n",
    "all_1 = np.hstack((image, avg, box))\n",
    "all_2 = np.hstack((gauss, median, bilateral))\n",
    "cv2.imshow('All Images', np.vstack((all_1, all_2)))\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:56:07.576585300Z",
     "start_time": "2024-04-28T03:55:55.539692600Z"
    }
   },
   "id": "c5f412d2013770b0"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
